﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using static MyGIS.GISShapefile;

namespace MyGIS
{


    public class GISVertex   //节点类
    {
        public double x;
        public double y;
        public GISVertex(double _x, double _y)//外部传参，向x与y赋值
        {
            x = _x;
            y = _y;
        }



        public GISVertex(BinaryReader br)//从文件中读取一个GISVertex实例
        {
            x = br.ReadDouble();
            y = br.ReadDouble();
        }


        public GISVertex(GISVertex v)//通过复制另一个GISVertex获得实例
        {
            CopyFrom(v);
        }


        public double Distance(GISVertex anothervertex)
        {
            return Math.Sqrt((x - anothervertex.x) *
                (x - anothervertex.x) + (y - anothervertex.y) * (y - anothervertex.y));
        }//计算两点间距离


        public void CopyFrom(GISVertex v)//使用输入点替换当前点
        {
            x = v.x;
            y = v.y;
        }


        /// <summary>
        /// 将点坐标输出到二进制文件
        /// </summary>
        /// <param name="bw"></param>
        public void WriteVertex(BinaryWriter bw)
        {
            bw.Write(x);
            bw.Write(y);
        }


        /// <summary>
        /// 判断两个节点在空间上是否重叠
        /// </summary>
        /// <param name="vertex"></param>
        /// <returns></returns>
        public bool IsSame(GISVertex vertex)
        {
            return x == vertex.x && y == vertex.y;
        }
    }


    public class GISPoint : GISSpatial  //点实体
    {

        public GISPoint(GISVertex onevertex)
        {
            centroid = onevertex;
            extent = new GISExtent(onevertex, onevertex);
        }//实例化点实体
        public override void draw(Graphics graphics, GISView view, bool Selected, GISThematic Thematic)//在屏幕上画出点实体
        {
            Point screenpoint = view.ToScreenPoint(centroid);
            SolidBrush brush = null;
            if (Selected)//根据点是否被选中设定不同颜色
            {
                brush = new SolidBrush(GISConst.SelectedPointColor);
            }
            else
            {
                brush = new SolidBrush(Thematic.InsideColor);
            }
            graphics.FillEllipse(brush,
            new Rectangle(screenpoint.X - Thematic.Size, screenpoint.Y - Thematic.Size,
                Thematic.Size * 2, Thematic.Size * 2));
            graphics.DrawEllipse(new Pen(new SolidBrush(Thematic.OutsideColor)),
                new Rectangle(screenpoint.X - Thematic.Size, screenpoint.Y - Thematic.Size, Thematic.Size * 2, Thematic.Size * 2));
        }
        public double Distance(GISVertex anothervertex)
        {
            return centroid.Distance(anothervertex);
        }//计算两点间距离
    }

    /// <summary>
    /// 线实体
    /// </summary>
    public class GISLine : GISSpatial
    {
        public List<GISVertex> Vertexs;
        public double Length;
        public GISLine(List<GISVertex> _vertexs)
        {
            if (_vertexs == null || _vertexs.Count < 2)
            {
                throw new ArgumentException("无效的输入节点");
            }
            Vertexs = _vertexs;
            centroid = GISTools.CalculateCentroid(_vertexs);
            extent = GISTools.CalculateExtent(_vertexs);
            Length = GISTools.CalculateLength(_vertexs);
        }
        public override void draw(Graphics graphics, GISView view, bool Selected, GISThematic Thematic)//画出Line
        {
            Point[] points = GISTools.GetScreenPoint(Vertexs, view);
            graphics.DrawLines(new Pen(Selected ? GISConst.SelectedLineColor : Thematic.InsideColor, Thematic.Size), points);
        }
        public GISVertex FromNode()//返回起始结点
        {
            return Vertexs[0];
        }
        public GISVertex ToNode()//返回终止结点
        {
            return Vertexs[Vertexs.Count - 1];
        }


        /// <summary>
        /// 计算输入点到线实体的距离
        /// </summary>
        /// <param name="vertex"></param>
        /// <returns></returns>
        public double Distance(GISVertex vertex)
        {
            double distance = Double.MaxValue;
            for (int i = 0; i < Vertexs.Count - 1; i++)//逐线段计算点到线段的距离，然后取最小值返回
            {
                distance = Math.Min(GISTools.PointToSegment(Vertexs[i], Vertexs[i + 1], vertex), distance);
            }
            return distance;
        }
    }


    /// <summary>
    /// 面实体
    /// </summary>
    public class GISPolygon : GISSpatial
    {
        public List<GISVertex> Vertexs;
        public double Area;
        public GISPolygon(List<GISVertex> _vertexs)
        {
            if (_vertexs == null || _vertexs.Count < 3)//当输入节点数不符合要求时抛出异常
            {
                throw new ArgumentException("无效的输入节点");
            }
            Vertexs = _vertexs;
            centroid = GISTools.CalculateCentroid(_vertexs);
            Area = GISTools.CalculateArea(_vertexs);
            extent = GISTools.CalculateExtent(_vertexs);
        }
        public override void draw(Graphics graphics, GISView view, bool Selected, GISThematic Thematic)//画出Polygon
        {
            Point[] points = GISTools.GetScreenPoint(Vertexs, view);
            graphics.FillPolygon(new SolidBrush(Selected ? GISConst.SelectedPolygonFillColor : Thematic.InsideColor), points);
            graphics.DrawPolygon(new Pen(Thematic.OutsideColor, Thematic.Size), points);
        }


        /// <summary>
        /// 射线法判断点是否落在面内（排除边缘）
        /// </summary>
        /// <param name="vertex"></param>
        /// <returns></returns>
        public bool Include(GISVertex vertex)
        {
            int count = 0;
            for (int i = 0; i < Vertexs.Count; i++)
            {
                if (Vertexs[i].IsSame(vertex))//点落在边界节点上
                    return false;
                int next = (i + 1) % Vertexs.Count;//next为下一个节点，与i节点构成线段
                //确定线段坐标极值
                double minX = Math.Min(Vertexs[i].x, Vertexs[next].x);
                double minY = Math.Min(Vertexs[i].y, Vertexs[next].y);
                double maxX = Math.Max(Vertexs[i].x, Vertexs[next].x);
                double maxY = Math.Max(Vertexs[i].y, Vertexs[next].y);
                if (minY == maxY)//若线段是平行的
                {
                    if (minY == vertex.y && vertex.x >= minX && vertex.x <= maxX)
                        return false;//点落在平行边上
                    else continue;
                }
                if (vertex.x > maxX || vertex.y > maxY || vertex.y < minY)//点在线段坐标极值之外
                    continue;
                double X0 = Vertexs[i].x + (vertex.y - Vertexs[i].y) * (Vertexs[next].x - Vertexs[i].x) / (Vertexs[next].y - Vertexs[i].y);//交点横坐标
                //纵坐标无需计算，为vertex.y
                if (X0 < vertex.x) continue;//交点在射线反方向，按无交点计
                if (X0 == vertex.x) return false;//交点为vertex，且在线段上
                if (vertex.y == minY) continue;
                count++;//其它情况，交点数+1
            }
            return count % 2 != 0;
        }
    }


    public class GISFeature   //空间要素特征类
    {
        public GISSpatial spatialpart;  //对象的空间信息
        public GISAttribute attributepart;  //对象的属性信息
        public bool Selected = false;//记录实例的选择状态
        public int ID;//空间对象的唯一标识符
        public GISFeature(GISSpatial spatial, GISAttribute attribute)
        {
            spatialpart = spatial;
            attributepart = attribute;
        }
        public void draw(Graphics graphics, GISView view, bool DrawAttributeOrNot, int index, GISThematic Thematic)
        {
            spatialpart.draw(graphics, view, Selected, Thematic);
            if (DrawAttributeOrNot)
            {
                attributepart.draw(graphics, view, spatialpart.centroid, index);
            }
        }
        public object GetAttribute(int index)
        {
            return attributepart.GetValue(index);
        }
    }


    public class GISAttribute
    {
        public ArrayList values = new ArrayList();
        public void AddValue(object o)  //添加属性值
        {
            values.Add(o);
        }
        public object GetValue(int index)  //获取属性值
        {
            return values[index];
        }
        public void draw(Graphics graphics, GISView view, GISVertex location, int index)
        {
            Point screenpoint = view.ToScreenPoint(location);
            graphics.DrawString(values[index].ToString(),
                new Font("宋体", 20),
                new SolidBrush(Color.Green),
                new PointF(screenpoint.X, screenpoint.Y));
        }//画出属性信息


        /// <summary>
        /// 返回属性字段的个数
        /// </summary>
        /// <returns></returns>
        public int ValueCount()
        {
            return values.Count;
        }
    }

    /// <summary>
    /// 抽象空间要素类
    /// </summary>
    public abstract class GISSpatial
    {
        public GISVertex centroid;//空间实体的中心点
        public GISExtent extent;//空间范围：最小外接矩形
        public abstract void draw(Graphics graphics, GISView view, bool Selected, GISThematic Thematic);
    }

    /// <summary>
    /// 空间对象的范围
    /// </summary>
    public class GISExtent
    {
        public GISVertex bottomleft;
        public GISVertex upright;
        public double ZoomingFactor = 2;//缩放系数，放大或缩小时会缩放为2倍或二分之一
        public double MovingFactor = 0.25;//移动系数，即移动一次会有四分之一的屏幕范围移除屏幕

        /// <summary>
        /// 显示范围（左下角点，右上角点）
        /// </summary>
        /// <param name="_bottomleft"></param>
        /// <param name="_upright"></param>
        public GISExtent(GISVertex _bottomleft, GISVertex _upright)
        {
            bottomleft = _bottomleft;
            upright = _upright;
        }



        public GISExtent(GISExtent extent)
        {
            upright = new GISVertex(extent.upright);
            bottomleft = new GISVertex(extent.bottomleft);
        }




        /// <summary>
        /// 输入坐标后自动判断左下角与右上角点
        /// </summary>
        /// <param name="_x1"></param>
        /// <param name="_x2"></param>
        /// <param name="_y1"></param>
        /// <param name="_y2"></param>
        public GISExtent(double _x1, double _x2, double _y1, double _y2)
        {
            if (_x1 < _x2)
            {
                if (_y1 < _y2)
                {
                    bottomleft = new GISVertex(_x1, _y1);
                    upright = new GISVertex(_x2, _y2);
                }
                else
                {
                    bottomleft = new GISVertex(_x1, _y2);
                    upright = new GISVertex(_x2, _y1);
                }
            }
            else
            {
                if (_y1 < _y2)
                {
                    bottomleft = new GISVertex(_x2, _y1);
                    upright = new GISVertex(_x1, _y2);
                }
                else
                {
                    bottomleft = new GISVertex(_x2, _y2);
                    upright = new GISVertex(_x1, _y1);
                }
            }
        }
        public double getMinX()
        {
            return bottomleft.x;
        }
        public double getMaxX()
        {
            return upright.x;
        }
        public double getMinY()
        {
            return bottomleft.y;
        }
        public double getMaxY()
        {
            return upright.y;
        }
        public double getWidth()  //计算地图横坐标长度
        {
            return upright.x - bottomleft.x;
        }
        public double getHeight()  //计算地图纵坐标长度
        {
            return upright.y - bottomleft.y;
        }
        public void ChangeExtent(GISMapActions actions)
        {
            double newminx = bottomleft.x, newminy = bottomleft.y,
                newmaxx = upright.x, newmaxy = upright.y;
            switch (actions)
            {
                case GISMapActions.zoomin:  //地图放大
                    newminx = ((getMinX() + getMaxX()) - getWidth() / ZoomingFactor) / 2;
                    newminy = ((getMinY() + getMaxY()) - getHeight() / ZoomingFactor) / 2;
                    newmaxx = ((getMinX() + getMaxX()) + getWidth() / ZoomingFactor) / 2;
                    newmaxy = ((getMinY() + getMaxY()) + getHeight() / ZoomingFactor) / 2;
                    break;
                case GISMapActions.zoomout:  //地图缩小
                    newminx = ((getMinX() + getMaxX()) - getWidth() * ZoomingFactor) / 2;
                    newminy = ((getMinY() + getMaxY()) - getHeight() * ZoomingFactor) / 2;
                    newmaxx = ((getMinX() + getMaxX()) + getWidth() * ZoomingFactor) / 2;
                    newmaxy = ((getMinY() + getMaxY()) + getHeight() * ZoomingFactor) / 2;
                    break;
                case GISMapActions.moveup:  //向上移动，即地图范围下移
                    newminy = getMinY() - getHeight() * MovingFactor;
                    newmaxy = getMaxY() - getHeight() * MovingFactor;
                    break;
                case GISMapActions.movedown:  //向下移动，即地图范围上移
                    newminy = getMinY() + getHeight() * MovingFactor;
                    newmaxy = getMaxY() + getHeight() * MovingFactor;
                    break;
                case GISMapActions.moveleft:  //向左移动
                    newminx = getMinX() + getWidth() * MovingFactor;
                    newmaxx = getMaxX() + getWidth() * MovingFactor;
                    break;
                case GISMapActions.moveright:  //向右移动
                    newminx = getMinX() - getWidth() * MovingFactor;
                    newmaxx = getMaxX() - getWidth() * MovingFactor;
                    break;
            }
            upright.x = newmaxx;
            upright.y = newmaxy;
            bottomleft.x = newminx;
            bottomleft.y = newminy;
        }

        public void CopyFrom(GISExtent extent)//使用Extent替换当前值
        {
            upright.CopyFrom(extent.upright);
            bottomleft.CopyFrom(extent.bottomleft);
        }


        /// <summary>
        /// 判断当前空间范围与另一空间范围是否相交
        /// </summary>
        /// <param name="extent"></param>
        /// <returns></returns>
        public bool InsertectOrNot(GISExtent extent)
        {
            return !(getMaxX() < extent.getMinX() || getMinX() > extent.getMaxX()
                || getMaxY() < extent.getMinY() || getMinY() > extent.getMaxY());
        }



        /// <summary>
        /// 计算显示范围的中心点坐标
        /// </summary>
        /// <returns></returns>
        public GISVertex GetCenter()
        {
            return new GISVertex((upright.x + bottomleft.x) / 2, (upright.y + bottomleft.y) / 2);
        }



        /// <summary>
        /// 合并两个图层的范围
        /// </summary>
        /// <param name="extent"></param>
        public void Merge(GISExtent extent)
        {
            upright.x = Math.Max(upright.x, extent.upright.x);
            upright.y = Math.Max(upright.y, extent.upright.y);
            bottomleft.x = Math.Max(bottomleft.x, extent.bottomleft.x);
            bottomleft.y = Math.Max(bottomleft.y, extent.bottomleft.y);
        }


        /// <summary>
        /// 判断当前空间范围是否包含输入的空间范围
        /// </summary>
        /// <param name="extent"></param>
        /// <returns></returns>
        public bool Include(GISExtent extent)
        {
            return (getMaxX() >= extent.getMaxX() && getMinX() <= extent.getMinX()
                && getMaxY() >= extent.getMaxY() && getMinY() <= extent.getMinY());
        }
    }



    public class GISView   //空间对象浏览类
    {
        GISExtent CurrentMapExtent;//记录显示的地图范围
        Rectangle MapWindowSize;  //记录绘图窗口的大小 
        double MapMinX, MapMinY;
        int WinW, WinH;
        double MapW, MapH;
        double ScaleX, ScaleY;
        public GISView(GISExtent _extent, Rectangle _rectangle)
        {
            UpdateMap(_extent, _rectangle);
        }

        /// <summary>
        /// 更新地图
        /// </summary>
        /// <param name="_extent"></param>
        /// <param name="_rectangle"></param>
        public void UpdateMap(GISExtent _extent, Rectangle _rectangle)
        {
            CurrentMapExtent = _extent;//当前地图范围
            MapWindowSize = _rectangle;
            WinW = MapWindowSize.Width;//窗口宽度
            WinH = MapWindowSize.Height;//窗口高度
            ScaleX = CurrentMapExtent.getWidth() / WinW;//比例尺=图上距离/实际距离
            ScaleY = CurrentMapExtent.getHeight() / WinH;
            ScaleX = Math.Max(ScaleX, ScaleY);
            ScaleY = ScaleX;
            MapW = MapWindowSize.Width * ScaleX;
            MapH = MapWindowSize.Height * ScaleY;
            GISVertex center = CurrentMapExtent.GetCenter();
            MapMinX = center.x - MapW / 2;//地图最小X坐标
            MapMinY = center.y - MapH / 2;//地图最小Y坐标
        }//更新地图

        public void UpdateExtent(GISExtent extent)//更新当前地图范围
        {
            CurrentMapExtent.CopyFrom(extent);
            UpdateMap(CurrentMapExtent, MapWindowSize);
        }

        public Point ToScreenPoint(GISVertex onevertex)//地图转屏幕点
        {
            double ScreenX = (onevertex.x - MapMinX) / ScaleX;
            double ScreenY = WinH - (onevertex.y - MapMinY) / ScaleY;
            return new Point((int)ScreenX, (int)ScreenY);
        }

        public GISVertex ToMapVertex(Point point)//屏幕转地图点
        {
            double MapX = ScaleX * point.X + MapMinX;
            double MapY = ScaleY * (WinH - point.Y) + MapMinY;
            return new GISVertex(MapX, MapY);
        }

        public void ChangeView(GISMapActions actions)//改变显示范围
        {
            CurrentMapExtent.ChangeExtent(actions);
            UpdateMap(CurrentMapExtent, MapWindowSize);
        }


        public double ToScreenDistance(GISVertex v1, GISVertex v2)//计算屏幕距离
        {
            Point p1 = ToScreenPoint(v1);
            Point p2 = ToScreenPoint(v2);
            double result = Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
            return result;
        }
        public double ToScreenDistance(double distance)
        {
            return ToScreenDistance(new GISVertex(0, 0), new GISVertex(0, distance));
        }


        /// <summary>
        /// 更新当前View的窗口尺寸
        /// </summary>
        /// <param name="rectangle"></param>
        public void UpdateRectangle(Rectangle rectangle)
        {
            MapWindowSize = rectangle;
            UpdateMap(CurrentMapExtent, MapWindowSize);
        }



        /// <summary>
        /// 获取实际的地图范围
        /// </summary>
        /// <returns></returns>
        public GISExtent GetRealExtent()
        {
            return new GISExtent(MapMinX, MapMinX + MapW, MapMinY, MapMinY + MapH);
        }


        /// <summary>
        /// 根据屏幕坐标极值生成地图范围
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="x2"></param>
        /// <param name="y1"></param>
        /// <param name="y2"></param>
        /// <returns></returns>
        public GISExtent RectToExtent(int x1, int x2, int y1, int y2)
        {
            GISVertex v1 = ToMapVertex(new Point(x1, y1));
            GISVertex v2 = ToMapVertex(new Point(x2, y2));
            return new GISExtent(v1.x, v2.x, v1.y, v2.y);
        }
    }

    public enum GISMapActions  //地图的缩放与平移操作
    {
        zoomin, zoomout,
        moveup, movedown, moveleft, moveright
    }

    class GISTools
    {
        public static GISVertex CalculateCentroid(List<GISVertex> _vertex)//计算空间实体中心点
        {
            if (_vertex.Count == 0) return null;
            double x = 0;
            double y = 0;
            for (int i = 0; i < _vertex.Count; i++)
            {
                x += _vertex[i].x;
                y += _vertex[i].y;
            }
            return new GISVertex(x / _vertex.Count, y / _vertex.Count);
        }
        public static GISExtent CalculateExtent(List<GISVertex> _vertex)//计算空间实体范围
        {
            if (_vertex.Count == 0) return null;
            double minx = Double.MaxValue;
            double miny = Double.MaxValue;
            double maxx = Double.MinValue;
            double maxy = Double.MinValue;
            for (int i = 0; i < _vertex.Count; i++)
            {
                if (_vertex[i].x < minx) minx = _vertex[i].x;
                if (_vertex[i].y < miny) miny = _vertex[i].y;
                if (_vertex[i].x > maxx) maxx = _vertex[i].x;
                if (_vertex[i].y > maxy) maxy = _vertex[i].y;
            }
            return new GISExtent(new GISVertex(minx, miny), new GISVertex(maxx, maxy));
        }

        public static double CalculateLength(List<GISVertex> _vertex)//计算线长度或面的周长（折线长度）
        {
            double length = 0;
            for (int i = 0; i < _vertex.Count - 1; i++)
            {
                length += _vertex[i].Distance(_vertex[i + 1]);
            }
            return length;
        }

        public static double CalculateArea(List<GISVertex> _vertex)//计算面实体的面积（利用矢量积计算）
        {
            double area = 0;
            for (int i = 0; i < _vertex.Count - 1; i++)
            {
                area += VectorProduct(_vertex[i], _vertex[i + 1]);
            }
            return area / 2;
        }


        /// <summary>
        /// 计算矢量积
        /// </summary>
        /// <param name="v1"></param>
        /// <param name="v2"></param>
        /// <returns></returns>
        public static double VectorProduct(GISVertex v1, GISVertex v2)
        {
            return v1.x * v2.y - v1.y * v2.x;
        }


        /// <summary>
        /// 把节点按当前的GISView转换成屏幕坐标
        /// </summary>
        /// <param name="_vertexs"></param>
        /// <param name="view"></param>
        /// <returns></returns>
        public static Point[] GetScreenPoint(List<GISVertex> _vertexs, GISView view)
        {
            Point[] points = new Point[_vertexs.Count];
            for (int i = 0; i < points.Length; i++)
            {
                points[i] = view.ToScreenPoint(_vertexs[i]);//对每个点调用ToScreenPoint方法
            }
            return points;
        }


        /// <summary>
        /// 将结构体转存为字节数组的方法
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static byte[] ToBytes(object c)
        {
            byte[] bytes = new byte[Marshal.SizeOf(c.GetType())];
            GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
            Marshal.StructureToPtr(c, handle.AddrOfPinnedObject(), false);
            handle.Free();
            return bytes;
        }


        /// <summary>
        /// 写入自定义格式中的文件字符串
        /// </summary>
        /// <param name="s"></param>
        /// <param name="bw"></param>
        public static void WriteString(string s, BinaryWriter bw)
        {
            bw.Write(StringLength(s));
            byte[] sbytes = Encoding.Default.GetBytes(s);//将字符串转换为字节数组
            bw.Write(sbytes);
        }


        /// <summary>
        /// 计算字符串中的字节数（因一个中文字符包含两个字节）
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static int StringLength(string s)
        {
            int ChineseCount = 0;
            byte[] bs = new ASCIIEncoding().GetBytes(s);
            foreach (byte b in bs)
                if (b == 0X3F) ChineseCount++;
            return ChineseCount + bs.Length;
        }


        /// <summary>
        /// 将给定的数据类型转换为整数
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static int TypeToInt(Type type)
        {
            ALLTYPES onetype = (ALLTYPES)Enum.Parse(typeof(ALLTYPES), type.ToString().Replace(".", "_"));
            return (int)onetype;
        }


        /// <summary>
        /// 从文件中读取结构体的实例
        /// </summary>
        /// <param name="br"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static Object FromBytes(BinaryReader br, Type type)
        {
            byte[] buff = br.ReadBytes(Marshal.SizeOf(type));//将与ShapefileHeader同样大小的字节赋给buff字符串
            GCHandle handle = GCHandle.Alloc(buff, GCHandleType.Pinned);//handle获取buff数组在内存中的指针
            Object result = Marshal.PtrToStructure(handle.AddrOfPinnedObject(), type);//该指针指向的内存被映射给ShapefileHeader结构体的实例header
            handle.Free();//释放指针
            return result;
        }


        /// <summary>
        /// 从文件中读取一个字符串
        /// </summary>
        /// <param name="br"></param>
        /// <returns></returns>
        public static string ReadString(BinaryReader br)
        {
            int length = br.ReadInt32();
            byte[] sbytes = br.ReadBytes(length);//读取字节数组
            return Encoding.Default.GetString(sbytes);//进行编码
        }


        /// <summary>
        /// 把从文件中读取到的整数转化为特定的数据类型
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public static Type IntToType(int index)
        {
            string typestring = Enum.GetName(typeof(ALLTYPES), index);
            typestring = typestring.Replace("_", ".");
            return Type.GetType(typestring);
        }


        /// <summary>
        /// 计算点C到线段AB的最短距离
        /// </summary>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <param name="C"></param>
        /// <returns></returns>
        /// {
        public static double PointToSegment(GISVertex A, GISVertex B, GISVertex C)
        {
            double dot1 = Dot3Product(A, B, C);
            if (dot1 > 0) return B.Distance(C);
            double dot2 = Dot3Product(B, A, C);
            if (dot2 > 0) return A.Distance(C);
            double dist = Cross3Product(A, B, C) / A.Distance(B);
            return Math.Abs(dist);
        }
        static double Dot3Product(GISVertex A, GISVertex B, GISVertex C)
        {
            GISVertex AB = new GISVertex(B.x - A.x, B.y - A.y);
            GISVertex BC = new GISVertex(C.x - B.x, C.y - B.y);
            return AB.x * BC.x + AB.y * BC.y;
        }
        static double Cross3Product(GISVertex A, GISVertex B, GISVertex C)
        {
            GISVertex AB = new GISVertex(B.x - A.x, B.y - A.y);
            GISVertex AC = new GISVertex(C.x - A.x, C.y - A.y);
            return VectorProduct(AB, AC);
        }


        public static Random rand = new Random();
        /// <summary>
        /// 获取随机颜色
        /// </summary>
        /// <returns></returns>
        public static Color GetRandomColor()
        {
            return Color.FromArgb(rand.Next(256), rand.Next(256), rand.Next(256));
        }



        /// <summary>
        /// 查找一组数据中的不同数值
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public static List<Object> FindUniqueValues(List<Object> values)
        {
            if (values.Count == 0)
                return null;
            values.Sort();//对输入值进行排序
            List<Object> UniqueValues = new List<object>();
            UniqueValues.Add(values[0]);
            for (int i = 0; i < values.Count; i++)
            {
                if (values[i].Equals(values[i - 1]) == false)
                {
                    UniqueValues.Add(values[i]);//发现不同值就存入UniqueValues中
                }
            }
            return UniqueValues;
        }


        /// <summary>
        /// 查找一组double数的分级点，按每级点数相同划分
        /// </summary>
        /// <param name="values"></param>
        /// <param name="levelNumber"></param>
        /// <returns></returns>
        public static List<double> FindLevels(List<double> values, int levelNumber)
        {
            if (values.Count == 0)
                return null;
            //确定每个级别的属性值数量
            int ValueNumber = values.Count / levelNumber;
            values.Sort();
            List<double> Levels = new List<double>();
            //寻找分割点
            for (int i = 0; i < values.Count; i += ValueNumber)
            {
                Levels.Add(values[i]);
            }
            //如果分割点多于分组数量，就去掉最后一个分割点
            if (Levels.Count > levelNumber)
            {
                Levels.RemoveAt(Levels.Count - 1);
            }
            return Levels;
        }



        /// <summary>
        /// 判断double数组中某一数属于哪一分组
        /// </summary>
        /// <param name="Levels"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int WhichLevel(List<double> Levels, double value)
        {
            //先判断是否属于最后一组以外的其他组
            for (int i = 0; i < Levels.Count - 1; i++)
            {
                if (value >= Levels[i] && value < Levels[i - 1])
                {
                    return i;
                }
            }
            //否则属于最后一组
            return Levels.Count - 1;
        }


        /// <summary>
        /// 根据颜色分级数生成渐变颜色
        /// </summary>
        /// <param name="levelIndex"></param>
        /// <param name="levelNumber"></param>
        /// <returns></returns>
        public static Color GetGradualColor(int levelIndex, int levelNumber)
        {
            int ColorLevel = (int)(255 - (float)levelIndex / levelNumber * 255);
            return Color.FromArgb(ColorLevel, ColorLevel, ColorLevel);
        }
    }


    /// <summary>
    /// 记录各种数据类型
    /// </summary>
    public enum ALLTYPES
    {
        System_Boolean,//布尔型
        System_Byte,//无符号8位整数
        System_Char,//字符型
        System_Decimal,//有符号128位实数
        System_Double,//有符号64位实数
        System_Single,//有符号32位实数
        System_Int32,//有符号32位整数
        System_Int64,//有符号64位整数
        System_SByte,//有符号8位整数
        System_Int16,//有符号16位整数
        System_String,//字符串
        System_UInt32,//无符号32位整数
        System_UInt64,//无符号64位整数
        System_UInt16//无符号16位整数
    }

    public class GISLayer
    {
        public string Name;//图层名称
        public GISExtent Extent;//地图范围
        public bool DrawAttributeOrNot = false;//绘制图层时是否标注属性信息
        public int LabelIndex;//需要标注的属性序列号
        public GISShapefile.SHAPETYPE ShapeType;//空间对象类型
        public bool Selectable = true;
        public bool Visible = true;
        public string Path = "";
        List<GISFeature> Features = new List<GISFeature>();//用于记录该图层中包含的所有空间对象实体
        public Dictionary<Object, GISThematic> Thematics;//图层唯一值制图样式
        public THEMATICTYPE ThematicType;
        public int ThematicFieldIndex;

        public List<GISField> Fields;

        public GISLayer(string _name, SHAPETYPE _shapetype, GISExtent _extent, List<GISField> _fields = null)
        {
            Name = _name;
            ShapeType = _shapetype;
            Extent = _extent;
            Fields = (_fields == null) ? new List<GISField>() : _fields;
            MakeUnifiedValueMap();
        }


        public void draw(Graphics graphics, GISView view, GISExtent extent = null)
        {
            extent = (extent == null) ? view.GetRealExtent() : extent;
            //唯一值地图
            if (ThematicType == THEMATICTYPE.UnifiedValue)
            {
                GISThematic Thematic = Thematics[ThematicType];
                for (int i = 0; i < Features.Count; i++)
                {
                    if (Extent.InsertectOrNot(Features[i].spatialpart.extent))
                    {
                        Features[i].draw(graphics, view, DrawAttributeOrNot, LabelIndex, Thematic);
                    }
                }
            }
            //独立值地图
            else if (ThematicType == THEMATICTYPE.UniqueValue)
            {
                for (int i = 0; i < Features.Count; i++)
                {
                    GISThematic Thematic = Thematics[Features[i].GetAttribute(ThematicFieldIndex)];
                    if (extent.InsertectOrNot(Features[i].spatialpart.extent))
                    {
                        Features[i].draw(graphics, view, DrawAttributeOrNot, LabelIndex, Thematic);
                    }
                }
            }
            //分级设色地图
            else if (ThematicType == THEMATICTYPE.GradualColor)
            {
                for (int i = 0; i < Features.Count; i++)
                {
                    GISThematic thematic = Thematics[LevelIndexs[i]];
                    if (extent.InsertectOrNot(Features[i].spatialpart.extent))
                    {
                        Features[i].draw(graphics, view, DrawAttributeOrNot, LabelIndex, thematic);
                    }
                }
            }
        }
        public void AddFeature(GISFeature feature)//添加要素
        {
            if (Features.Count == 0)
                feature.ID = 0;
            else
                feature.ID = Features[Features.Count - 1].ID + 1;//令新增的空间对象的ID为已有对象中的最大ID+1
            Features.Add(feature);
        }
        public int FeatureCount()//用于获取Feature中元素的数量
        {
            return Features.Count;
        }


        /// <summary>
        /// 根据Feature数组中的序号获得GISFeature
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        public GISFeature GetFeature(int i)
        {
            return Features[i];
        }

        public List<GISFeature> GetAllFeatures()
        {
            return Features;
        }


        /// <summary>
        /// 空间对象选中集
        /// </summary>
        public List<GISFeature> Selection = new List<GISFeature>();


        /// <summary>
        /// 点选空间对象
        /// </summary>
        public SelectResult Select(GISVertex vertex, GISView view)
        {
            GISSelect select = new GISSelect();
            SelectResult sr = select.Select(vertex, Features, ShapeType, view);
            if (sr == SelectResult.OK)
            {
                if (ShapeType == SHAPETYPE.poloygon)//面实体的选择
                {
                    for (int i = 0; i < select.SelectedFeatures.Count; i++)
                    {
                        if (select.SelectedFeatures[i].Selected == false)//如果该空间对象尚未被选择
                        {
                            select.SelectedFeatures[i].Selected = true;//就将它添加到被选中数组中
                            Selection.Add(select.SelectedFeatures[i]);
                        }
                    }
                }
                else//点实体和线实体的选择
                {
                    if (select.SelectedFeature.Selected == false)
                    {
                        select.SelectedFeature.Selected = true;
                        Selection.Add(select.SelectedFeature);
                    }
                }
            }
            return sr;
        }

        /// <summary>
        /// 框选空间对象
        /// </summary>
        /// <param name="extent"></param>
        /// <returns></returns>
        public SelectResult Select(GISExtent extent)
        {
            GISSelect gs = new GISSelect();
            SelectResult sr = gs.Select(extent, Features);
            if (sr == SelectResult.OK)
            {
                for (int i = 0; i < gs.SelectedFeatures.Count; i++)
                {
                    if (gs.SelectedFeatures[i].Selected == false)
                    {
                        gs.SelectedFeatures[i].Selected = true;
                        Selection.Add(gs.SelectedFeatures[i]);
                    }
                }
            }
            return sr;
        }



        /// <summary>
        /// 清除空间对象的选择
        /// </summary>
        public void ClearSelection()
        {
            for (int i = 0; i < Selection.Count; i++)
            {
                Selection[i].Selected = false;
            }
            Selection.Clear();
        }


        /// <summary>
        /// 通过ID找到GISFeature并将其添加到Selection中
        /// </summary>
        /// <param name="id"></param>
        public void AddSelectedFeatureByID(int id)
        {
            GISFeature feature = GetFeatureByID(id);
            feature.Selected = true;
            Selection.Add(feature);
        }


        /// <summary>
        /// 通过ID找GISFeature
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public GISFeature GetFeatureByID(int id)
        {
            foreach (GISFeature feature in Features)
            {
                if (feature.ID == id)
                    return feature;
            }
            return null;
        }


        /// <summary>
        /// 绘制唯一值地图
        /// </summary>
        public void MakeUnifiedValueMap()
        {
            ThematicType = THEMATICTYPE.UnifiedValue;
            Thematics.Clear();
            Thematics.Add(ThematicType, new GISThematic(ShapeType));
        }



        /// <summary>
        /// 绘制独立值地图
        /// </summary>
        /// <param name="FieldIndex"></param>
        public void MakeUniqueValueMap(int FieldIndex)
        {
            //修改专题地图样式
            ThematicType = THEMATICTYPE.UniqueValue;
            //确定专题地图的属性字段
            ThematicFieldIndex = FieldIndex;
            //获取属性值
            List<object> values = new List<object>();
            for (int i = 0; i < Features.Count; i++)
            {
                values.Add(Features[i].GetAttribute(ThematicFieldIndex));
            }
            //获取独立值
            List<object> UniqueValues = GISTools.FindUniqueValues(values);
            //获取目前的一些显示设置，这些设置将保持不变
            Color OutsideColor = default(Color);
            int Size = 0;
            foreach (GISThematic Thematic in Thematics.Values)
            {
                OutsideColor = Thematic.OutsideColor;
                Size = Thematic.Size;
                break;
            }
            //构建Thematics,其中用InsideColor来区别具有不同独立值的空间对象
            Thematics.Clear();
            foreach (Object o in UniqueValues)
            {
                GISThematic Thematic = new GISThematic(OutsideColor, Size, GISTools.GetRandomColor());
                Thematics.Add(o, Thematic);
            }
        }


        public List<int> LevelIndexs = new List<int>();
        public bool MakeGradualColor(int FieldIndex, int LevelNumber)
        {
            List<double> values = new List<double>();
            //尝试把属性值转成double类型的列表
            try
            {
                for (int i = 0; i < Features.Count; i++)
                {
                    values.Add(Convert.ToDouble(Features[i].GetAttribute(ThematicFieldIndex).ToString()));
                }
            }
            //如果不成功，说明属性值不是数值型的
            catch
            {
                return false;
            }
            //修改专题地图样式
            ThematicType = THEMATICTYPE.GradualColor;
            //确定专题地图所用属性字段
            ThematicFieldIndex = FieldIndex;
            //获取分级关键点
            List<double> levels = GISTools.FindLevels(values, LevelNumber);
            //清空每个空间对象的分级序号
            LevelIndexs.Clear();
            //计算每个属性值的分级序号
            for (int i = 0; i < Features.Count; i++)
            {
                int LevelIndex = GISTools.WhichLevel(levels, Convert.ToDouble(Features[i].GetAttribute(ThematicFieldIndex).ToString());
                LevelIndexs.Add(LevelIndex);
            }
            //获取目前的一些显示设置，这些设置将保持不变
            Color OutsideColor = Color.Beige;
            int Size = 0;
            foreach (GISThematic Thematic in Thematics.Values)
            {
                OutsideColor = Thematic.OutsideColor;
                Size = Thematic.Size;
                break;
            }
            //构建Thematics，为每个级别确定一个绘图样式
            Thematics.Clear();
            for (int i = 0; i < LevelNumber; i++)
            {
                Thematics.Add(i, new GISThematic(OutsideColor, Size,
                    GISTools.GetGradualColor(i, LevelNumber)));
            }
            return true;
        }
    }

    /// <summary>
    /// 记录字段的数据类型和名称
    /// </summary>
    public class GISField
    {
        public Type datatype;
        public string name;
        public GISField(Type type, string name)
        {
            datatype = type;
            this.name = name;
        }
    }



    /// <summary>
    /// 记录点选操作后的反馈状态
    /// </summary>
    public enum SelectResult
    {
        OK,//正常选择状态：选择到一个结果
        EmptySet,//错误选择状态：备选集为空
        TooFar,//错误选择状态：点击选择时距离空间对象太远
        UnknownType//错误选择状态：未知空间对象
    }


    public class GISSelect
    {
        public GISFeature SelectedFeature = null;//被选中的点要素或线要素
        public List<GISFeature> SelectedFeatures = new List<GISFeature>();//被选中的面要素或框选产生的多个要素


        /// <summary>
        /// 返回点选选择结果
        /// </summary>
        /// <param name="vertex"></param>
        /// <param name="features"></param>
        /// <param name="shapetype"></param>
        /// <param name="view"></param>
        /// <returns></returns>
        public SelectResult Select(GISVertex vertex, List<GISFeature> features, SHAPETYPE shapetype, GISView view)
        {
            if (features.Count == 0)
                return SelectResult.EmptySet;
            GISExtent MinSelectExtent = BuildExtent(vertex, view);//最小选择范围，是一个2倍距离阈值边长的正方形范围
            switch (shapetype)
            {
                case SHAPETYPE.point:
                    return SelectPoint(vertex, features, view, MinSelectExtent);
                case SHAPETYPE.line:
                    return SelectLine(vertex, features, view, MinSelectExtent);
                case SHAPETYPE.poloygon:
                    return SelectPolygon(vertex, features, view, MinSelectExtent);
            }
            return SelectResult.UnknownType;
        }
        /// <summary>
        /// 返回框选选择结果
        /// </summary>
        /// <param name="extent"></param>
        /// <param name="features"></param>
        /// <returns></returns>
        public SelectResult Select(GISExtent extent, List<GISFeature> features)
        {
            SelectedFeatures.Clear();
            for (int i = 0; i < features.Count; i++)
            {
                if (extent.Include(features[i].spatialpart.extent))
                {
                    SelectedFeatures.Add(features[i]);
                }
            }
            return (SelectedFeatures.Count > 0) ?
                SelectResult.OK : SelectResult.TooFar;
        }


        /// <summary>
        /// 建立最小选择范围MinSelectExtent
        /// </summary>
        /// <param name="vertex"></param>
        /// <param name="view"></param>
        /// <returns></returns>
        public GISExtent BuildExtent(GISVertex vertex, GISView view)
        {
            Point p0 = view.ToScreenPoint(vertex);//点击位置的屏幕坐标
            Point p1 = new Point(p0.X + (int)GISConst.MinScreenDistance, p0.Y + (int)GISConst.MinScreenDistance);//最小选择范围的右上角点
            Point p2 = new Point(p0.X - (int)GISConst.MinScreenDistance, p0.Y - (int)GISConst.MinScreenDistance);//最小选择范围的左下角点
            GISVertex gp1 = view.ToMapVertex(p1);
            GISVertex gp2 = view.ToMapVertex(p2);
            return new GISExtent(gp1.x, gp2.x, gp1.y, gp2.y);
        }



        /// <summary>
        /// 点选点实体
        /// </summary>
        /// <param name="vertex"></param>
        /// <param name="features"></param>
        /// <param name="view"></param>
        /// <param name="MinSelectExtent"></param>
        /// <returns></returns>
        public SelectResult SelectPoint(GISVertex vertex, List<GISFeature> features, GISView view, GISExtent MinSelectExtent)
        {
            Double distance = Double.MaxValue;
            int id = -1;//距离Vertex最近的一个GISFeature实例的序号
            for (int i = 0; i < features.Count; i++)
            {
                if (MinSelectExtent.InsertectOrNot
                       (features[i].spatialpart.extent) == false) continue;//粗选，判断最小选择范围与当前空间对象是否相交
                GISPoint point = (GISPoint)(features[i].spatialpart);
                double dist = point.Distance(vertex);
                if (dist < distance)
                {
                    distance = dist;
                    id = i;
                }
            }
            if (id == -1)//无法通过粗选
            {
                SelectedFeature = null;
                return SelectResult.TooFar;
            }
            else//通过粗选，进行精选
            {
                double screendistance = view.ToScreenDistance(vertex, features[id].spatialpart.centroid);
                if (screendistance <= GISConst.MinScreenDistance)
                {
                    SelectedFeature = features[id];
                    return SelectResult.OK;
                }
                else
                {
                    SelectedFeature = null;
                    return SelectResult.TooFar;
                }
            }
        }




        /// <summary>
        /// 点选线实体
        /// </summary>
        /// <param name="vertex"></param>
        /// <param name="features"></param>
        /// <param name="view"></param>
        /// <param name="MinSelectExtent"></param>
        /// <returns></returns>
        public SelectResult SelectLine(GISVertex vertex, List<GISFeature> features, GISView view, GISExtent MinSelectExtent)
        {
            Double distance = Double.MaxValue;
            int id = -1;//距离Vertex最近的一个GISFeature实例的序号
            for (int i = 0; i < features.Count; i++)
            {
                if (MinSelectExtent.InsertectOrNot
                       (features[i].spatialpart.extent) == false) continue;//粗选，判断最小选择范围与当前空间对象是否相交
                GISLine line = (GISLine)(features[i].spatialpart);
                double dist = line.Distance(vertex);
                if (dist < distance)
                {
                    distance = dist;
                    id = i;
                }
            }
            if (id == -1)//无法通过粗选
            {
                SelectedFeature = null;
                return SelectResult.TooFar;
            }
            else//通过粗选，进行精选
            {
                double screendistance = view.ToScreenDistance(distance);
                if (screendistance <= GISConst.MinScreenDistance)
                {
                    SelectedFeature = features[id];
                    return SelectResult.OK;
                }
                else
                {
                    SelectedFeature = null;
                    return SelectResult.TooFar;
                }
            }
        }


        /// <summary>
        /// 点选面实体
        /// </summary>
        /// <param name="vertex"></param>
        /// <param name="features"></param>
        /// <param name="view"></param>
        /// <param name="MinSelectExtent"></param>
        /// <returns></returns>
        public SelectResult SelectPolygon(GISVertex vertex, List<GISFeature> features, GISView view, GISExtent MinSelectExtent)
        {
            SelectedFeatures.Clear();
            for (int i = 0; i < features.Count; i++)
            {
                if (MinSelectExtent.InsertectOrNot(features[i].spatialpart.extent) == false) continue;//进行粗选
                GISPolygon polygon = (GISPolygon)(features[i].spatialpart);
                if (polygon.Include(vertex))//精选，判断点是否落在面实体内
                    SelectedFeatures.Add(features[i]);
            }
            if (SelectedFeatures.Count > 0)
                return SelectResult.OK;
            else
                return SelectResult.TooFar;
        }

    }



    /// <summary>
    /// 常量类
    /// </summary>
    public class GISConst
    {
        internal static double MinScreenDistance = 5;//屏幕点选距离阈值
        public static double ZoomInFactor = 0.8;//地图放大系数
        public static double ZoomOutFactor = 0.8;//地图缩小系数
        //点的颜色与大小
        public static Color PointColor = Color.Pink;
        public static int PointSize = 3;
        public static Color SelectedPointColor = Color.Red;
        //线的颜色与宽度
        public static Color LineColor = Color.CadetBlue;
        public static int LineWidth = 2;
        public static Color SelectedLineColor = Color.Blue;
        //面的颜色与边框宽度
        public static Color PolygonBoundaryColor = Color.White;
        public static Color PolygonFillColor = Color.LightSteelBlue;
        public static int PolygoBoundaryWidth = 2;
        public static Color SelectedPolygonFillColor = Color.Yellow;
        //绘制选择或缩放范围框时的填充颜色
        public static Color ZoomSelectBoxColor = Color.FromArgb(50, 0, 0, 100);
        //Shapefile文件扩展名
        public static string SHPFILE = "shp";
        //自定义文件扩展名
        public static string MYFILE = "mygis";
        //地图文档扩展名
        public static string MYDOC = "mydoc";
    }




    /// <summary>
    /// 多图层类
    /// </summary>
    public class GISDocument
    {
        public List<GISLayer> layers = new List<GISLayer>();
        public GISExtent extent;



        /// <summary>
        /// 通过图层名称获得图层
        /// </summary>
        /// <param name="layerName"></param>
        /// <returns></returns>
        public GISLayer GetLayer(string layerName)
        {
            for (int i = 0; i < layers.Count; i++)
            {
                if (layers[i].Name == layerName)
                    return layers[i];
            }
            return null;
        }



        /// <summary>
        /// 添加图层
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public GISLayer AddLayer(string path)
        {
            GISLayer layer = null;
            string fileType = System.IO.Path.GetExtension(path).ToLower();
            if (fileType == "." + GISConst.SHPFILE)
            {
                layer = GISShapefile.ReadShapefile(path);
            }
            else if (fileType == "." + GISConst.MYFILE)
            {
                layer = GISMyFile.ReadFile(path);
            }
            layer.Path = path;
            GetUniqueName(layer);
            layers.Add(layer);
            UpdateExtent();
            return layer;
        }


        /// <summary>
        /// 移除图层
        /// </summary>
        /// <param name="layerName"></param>
        public void RemoveLayer(string layerName)
        {
            layers.Remove((GetLayer(layerName)));
            UpdateExtent();
        }


        /// <summary>
        /// 获取唯一图层名，若重复则对新图层改名
        /// </summary>
        /// <param name="layer"></param>
        private void GetUniqueName(GISLayer layer)
        {
            List<string> names = new List<string>();
            //对当前所有图层名进行排序
            for (int i = 0; i < layers.Count; i++)
            {
                names.Add(layers[i].Name);
            }
            names.Sort();
            for (int i = 0; i < names.Count; i++)
            {
                if (layer.Name == names[i])
                {
                    layer.Name = names[i] + "(1)";
                }
            }
        }



        /// <summary>
        /// 更新图层组的地图范围
        /// </summary>
        public void UpdateExtent()
        {
            extent = null;
            if (layers.Count == 0)
                return;
            extent = new GISExtent(layers[0].Extent);
            for (int i = 0; i < layers.Count; i++)
            {
                extent.Merge(layers[i].Extent);
            }
        }


        /// <summary>
        /// 画出图层组中的可见图层
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="view"></param>
        public void Draw(Graphics graphics, GISView view)
        {
            if (layers.Count == 0)
                return;
            GISExtent displayextent = view.GetRealExtent();
            for (int i = 0; i < layers.Count; i++)
            {
                if (layers[i].Visible)
                {
                    layers[i].draw(graphics, view, displayextent);
                }
            }
        }



        /// <summary>
        /// 调整图层显示顺序
        /// </summary>
        /// <param name="name1"></param>
        /// <param name="name2"></param>
        public void SwitchLayer(string name1, string name2)
        {
            GISLayer layer1 = GetLayer(name1);
            GISLayer layer2 = GetLayer(name2);
            int index1 = layers.IndexOf(layer1);
            int index2 = layers.IndexOf(layer2);
            layers[index1] = layer2;
            layers[index2] = layer1;
        }



        /// <summary>
        /// 写入工程文档
        /// </summary>
        /// <param name="filename"></param>
        public void Write(string filename)
        {
            FileStream fsr = new FileStream(filename, FileMode.Create);
            BinaryWriter bw = new BinaryWriter(fsr);
            for (int i = 0; i < layers.Count; i++)
            {
                GISTools.WriteString(layers[i].Path, bw);
                bw.Write(layers[i].DrawAttributeOrNot);
                bw.Write(layers[i].LabelIndex);
                bw.Write(layers[i].Selectable);
                bw.Write(layers[i].Visible);
            }
            bw.Close();
            fsr.Close();
        }


        public void Read(string filename)
        {
            layers.Clear();
            FileStream fsr = new FileStream(filename, FileMode.Open);
            BinaryReader br = new BinaryReader(fsr);
            while (br.PeekChar() != -1)
            {
                string path = GISTools.ReadString(br);
                GISLayer layer = AddLayer(path);
                layer.Path = path;
                layer.DrawAttributeOrNot = br.ReadBoolean();
                layer.LabelIndex = br.ReadInt32();
                layer.Selectable = br.ReadBoolean();
                layer.Visible = br.ReadBoolean();
            }
            br.Close();
            fsr.Close();
        }



        /// <summary>
        /// 判断GISDocument是否为空，为空则返回true
        /// </summary>
        /// <returns></returns>
        public bool IsEmpty()
        {
            return (layers.Count == 0);
        }



        /// <summary>
        /// 清空所有图层的选择项
        /// </summary>
        public void ClearSelection()
        {
            for (int i = 0; i < layers.Count; i++)
            {
                layers[i].ClearSelection();
            }
        }


        /// <summary>
        /// 选择图层
        /// </summary>
        /// <param name="v"></param>
        /// <param name="view"></param>
        /// <returns></returns>
        public SelectResult Select(GISVertex v, GISView view)
        {
            SelectResult sr = SelectResult.TooFar;
            for (int i = 0; i < layers.Count; i++)
            {
                if (layers[i].Selectable)
                {
                    if (layers[i].Select(v, view) == SelectResult.OK)
                    {
                        sr = SelectResult.OK;
                    }
                }
            }
            return sr;
        }
        public SelectResult Select(GISExtent extent)
        {
            SelectResult sr = SelectResult.TooFar;
            for (int i = 0; i < layers.Count; i++)
            {
                if (layers[i].Selectable)
                {
                    if (layers[i].Select(extent) == SelectResult.OK)//对图层组中的每个图层调用Select函数
                    {
                        //如果至少一个图层被选择成功，则整个过程的结果被标记为“OK”
                        sr = SelectResult.OK;
                    }
                }
            }
            return sr;
        }
    }



    /// <summary>
    /// 鼠标动作枚举类
    /// </summary>
    public enum MOUSECOMMAND
    {
        Unused,//空
        Select,//选择
        ZoomIn,//放大
        ZoomOut,//缩小
        Pan//平移
    }



    public class GISThematic
    {
        public Color OutsideColor;//代表边界颜色，对线对象无意义
        public int Size;//代表点的半径或线的宽度或面的边界宽度
        public Color InsideColor;//代表填充颜色

        public GISThematic(Color OutsideColor, int size, Color insideColor)
        {
            Update(OutsideColor, size, insideColor);
        }
        public GISThematic(SHAPETYPE _shapetype)
        {
            if (_shapetype == SHAPETYPE.point)
            {
                Update(GISTools.GetRandomColor(), GISConst.PointSize, GISTools.GetRandomColor());
            }
            else if (_shapetype == SHAPETYPE.line)
            {
                Update(GISTools.GetRandomColor(), GISConst.LineWidth, GISTools.GetRandomColor());
            }
            else if (_shapetype == SHAPETYPE.poloygon)
            {
                Update(GISTools.GetRandomColor(), GISConst.PolygoBoundaryWidth, GISTools.GetRandomColor());
            }
        }

        public void Update(Color OutsideColor, int size, Color insideColor)
        {
            OutsideColor = OutsideColor;
            Size = size;
            InsideColor = insideColor;
        }
    }


    /// <summary>
    /// 专题地图类型枚举类
    /// </summary>
    public enum THEMATICTYPE
    {
        UnifiedValue,//唯一值地图
        UniqueValue,//独立值地图
        GradualColor//分级设色地图
    }

}
